package edu.ustb.aur.moldpackage;

import java.util.*;

import javax.annotation.PostConstruct;

import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import edu.ustb.aur.assetpackage.Asset;
import edu.ustb.aur.assetpackage.AssetService;
import edu.ustb.aur.myenum.MoldEnum;
import edu.ustb.aur.myenum.RightEnum;
import edu.ustb.aur.rightpackage.AbstractRight;

/**
 * @author Maker-Mr.Yao
 */
@Component
public class CarMold extends AbstractMold {
    /*
    对于Car类来说，有哪些权利？又有哪些操作呢？
    分析：（最好别删，可以保留到最后再删，不想看到可以点旁边的减号折叠起来(^V^)）
    首先，Car类应该具有属性： 
    1.权属列表
      四大基本权利：
      使用权：
      收益权：收益权是指获取基于所有者财产而产生的经济利益的可能性
      占有权：
      处分权：处分权是财产所有人对其财产在法律规定的范围内最终处理的权利，即决定财产在事实上或法律上命运的权利。
             包括资产的转让、消费、出售、销毁、丢弃处理等方面的权利。处分权是所有权四项权能的核心，是财产所有人最基本的权利。
             处分权在多数情况下由所有人享有，但在某些情况下，也可以使所有权与处分权分离，形成非所有权依法享有的处分权。
    
    然后，Car类应该具有方法：（整体上与HouseMold类似，只是某些方法在细节上有些许差别）
    1.买卖：
      必须拥有车的使用权和占有权，即车不能进行买卖，如果车正在被出租
    2.租赁：
      使用权、占有权肯定转让了，但是 收益权呢？分两种：
      a.将车租出去产生的；b.跑车产生的
      如何区分呢？也不用，只要没有处分权，那么就不能再把车出租出去（所以之前写的HouseMold中的租赁有问题）
      存不存在拥有处分权，但是没有收益权这种情况呢？
      不可能，收益权和处分权是互相依存的关系，至少在出租这个问题上是这样的，即脱离了收益权谈处分权是没有意义的
      举个例子，根据处分权的定义，具有处分权的人可以对房屋进行出售，而出售房屋所获得却属于房屋的收益权。
      这样看来，好多操作其实都是需要四项基本权利的，那么将四项基本权利拆分的意义在哪呢？
    3.抵押 
      应该是与HouseMold完全相同的
    4.馈赠 
      与HouseMold完全相同的
    5.销毁
      与HouseMold完全相同的
      注：在Car这个问题上，我觉得许多操作的阈值都应该设置为1才行
    * */

//    @Autowired
//    private AssetService assetService;
//
//    private static CarMold carMold;

    /**
     * 添加日志对象
     */
//    private Logger log = LoggerFactory.getLogger(getClass());

//    /**
//     * 通过@PostConstruct实现初始化bean之前进行的操作
//     */
//    @PostConstruct
//    public void init() {
//        carMold = this;
//        carMold.assetService = this.assetService;
//    }

    /**
     * 默认构造函数
     */
    public CarMold() {
        // 调用父类默认构造函数
        super();
        type = "CAR_MOLD";
    }

    /**
     * 含参构造函数
     * 
     * @param moldMap
     *            资产对象与权利对象的映射
     */
    public CarMold(HashMap<RightEnum, AbstractRight> moldMap, double threshold) {
        // 调用父类含参构造函数
        super(moldMap, threshold);
        type = "CAR_MOLD";
    }

    /**
     * 售卖操作，判断各权利是否均操作阈值，符合条件就执行。同意者的rightMap各权利之和超过阈值，强制执行此操作，原权利映射注销，新的权利映射建立 规定了售卖操作需要具有的权利，规定了售卖操作需要完成的权利转移
     * 目前假定进行售卖操作，需要具有收益权，占有权，处分权，使用权，并且其具有的比例操作阈值
     *
     * @param moldMap
     *            资产对象与权利对象的映射hashMap
     * @param froms
     *            调用此操作的同意者数组
     * @param toRightMap
     *            此操作执行成功后，接收者的分配rightMap
     * @return true or false
     */
    @Override
    public boolean sell(HashMap<RightEnum, AbstractRight> moldMap, String[] froms, HashMap<String, Double> toRightMap) {

        // 1. 通过isHasImplementRight函数判断是否具有相应的操作权利
        if (!isHasImplementRight(MoldEnum.SELL_MOLD, moldMap, froms, this.threshold)) {
            // 没有相关操作权利
//            log.error("该用户组无权对该资产进行操作");
            return false;
        }

//        log.info("该用户组有权对该资产进行操作");

        // 2. 调用对应的权利注销函数，注销所有映射
        for (RightEnum rightEnum : operateTypeRightList(MoldEnum.SELL_MOLD)) {
            // 删除moldMap中rightEnum的映射关系
            // 在sell操作中，一旦可以进行sell，应该注销掉所有用户的权利，而不仅仅是froms里的用户
            Set<String> userAddressSet = new HashSet<>(moldMap.get(rightEnum).rightMap.keySet());
            for (String userAddress : userAddressSet) {
                moldMap.get(rightEnum).deleteRight(userAddress, moldMap.get(rightEnum).rightMap.get(userAddress));
            }

            // 测试专用，输出变更后的资产权属
//            log.info(JSONObject.toJSONString(moldMap));
        }

        // 3. 调用对应的权利建立函数
        for (RightEnum rightEnum : operateTypeRightList(MoldEnum.SELL_MOLD)) {
            for (String userAddress : toRightMap.keySet()) {
                moldMap.get(rightEnum).initRight(userAddress, toRightMap.get(userAddress));
                if (!moldMap.containsKey(rightEnum)) {
                    // 不存在则返回false，映射关系应该上一步中添加了
                    return false;
                }
            }

            // 测试专用，输出变更后的资产权属
//            log.info(JSONObject.toJSONString(moldMap));
        }
        return true;
    }

    /**
     * 租赁操作，判断各权利是否均操作阈值，符合条件就执行。 规定了租赁操作需要具有的权利，规定了租赁操作需要完成的权利转移 目前假定进行租赁操作，需要具有收益权，使用权，占有权，并且其具有的比例操作阈值
     *
     * @param moldMap
     *            资产对象与权利对象的映射hashMap
     * @param froms
     *            调用此操作的同意者数组
     * @param toRightMap
     *            此操作执行成功后，接收者的分配rightMap
     * @return true or false
     */
    @Override
    public boolean lease(HashMap<RightEnum, AbstractRight> moldMap, String[] froms,
        HashMap<String, Double> toRightMap) {
        // 1. 通过isHasImplementRight函数判断是否具有相应的操作权利
        if (!isHasImplementRight(MoldEnum.LEASE_MOLD, moldMap, froms, this.threshold)) {
            // 没有相关操作权利
//            log.error("该用户组无权对该资产进行操作");
            return false;
        }

        // 2. 调用对应的权利注销函数，注销所有映射
        for (RightEnum rightEnum : operateTypeRightList(MoldEnum.LEASE_MOLD)) {
            // 删除moldMap中rightEnum的映射关系
            for (String userAddress : froms) {
                if (!rightEnum.equals(RightEnum.USUFRUCT_RIGHT) && !rightEnum.equals(RightEnum.DISPOSE_RIGHT)) {
                    moldMap.get(rightEnum).deleteRight(userAddress, moldMap.get(rightEnum).rightMap.get(userAddress));
                }
            }
        }

        // 3. 调用对应的权利建立函数
        for (RightEnum rightEnum : operateTypeRightList(MoldEnum.LEASE_MOLD)) {
            for (String userAddress : toRightMap.keySet()) {
                if (!rightEnum.equals(RightEnum.USUFRUCT_RIGHT) && !rightEnum.equals(RightEnum.DISPOSE_RIGHT)) {
                    moldMap.get(rightEnum).initRight(userAddress, toRightMap.get(userAddress));
                }
                if (!moldMap.containsKey(rightEnum)) {
                    // 不存在则返回false，映射关系应该上一步中添加了
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 租赁返回操作
     *
     * @param moldMap
     *            资产对象与权利对象的映射hashMap
     * @param froms
     *            调用此操作的同意者数组
     * @param toRightMap
     *            此操作执行成功后，接收者的分配rightMap
     * @return true or false
     */
    @Override
    public boolean leaseReturn(HashMap<RightEnum, AbstractRight> moldMap, String[] froms,
                         HashMap<String, Double> toRightMap) {
        // 1. 通过isHasImplementRight函数判断是否具有相应的操作权利
        if (!isHasImplementRight(MoldEnum.LEASEReturn_MOLD, moldMap, froms, this.threshold)) {
            // 没有相关操作权利
//            log.error("该用户组无权对该资产进行操作");
            return false;
        }

        // 2. 调用对应的权利注销函数，注销所有映射
        for (RightEnum rightEnum : operateTypeRightList(MoldEnum.LEASEReturn_MOLD)) {
            // 删除moldMap中rightEnum的映射关系
            for (String userAddress : froms) {
                if (!rightEnum.equals(RightEnum.USUFRUCT_RIGHT) && !rightEnum.equals(RightEnum.DISPOSE_RIGHT)) {
                    moldMap.get(rightEnum).deleteRight(userAddress, moldMap.get(rightEnum).rightMap.get(userAddress));
                }
            }
        }

        // 3. 调用对应的权利建立函数
        for (RightEnum rightEnum : operateTypeRightList(MoldEnum.LEASEReturn_MOLD)) {
            for (String userAddress : toRightMap.keySet()) {
                if (!rightEnum.equals(RightEnum.USUFRUCT_RIGHT) && !rightEnum.equals(RightEnum.DISPOSE_RIGHT)) {
                    moldMap.get(rightEnum).initRight(userAddress, toRightMap.get(userAddress));
                }
                if (!moldMap.containsKey(rightEnum)) {
                    // 不存在则返回false，映射关系应该上一步中添加了
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 抵押操作，判断各权利是否均操作阈值，符合条件就执行。 规定了抵押操作需要具有的权利，规定了抵押操作需要完成的权利转移 目前假定进行抵押操作，需要具有处分权，并且其具有的比例操作阈值
     * 由抵押操作产生的担保物权，不属于四项基本权利，关于这点还值得商榷，目前的采取的办法是将处分权移交（但明显没道理）
     *
     * @param moldMap
     *            资产对象与权利对象的映射hashMap
     * @param froms
     *            调用此操作的同意者数组
     * @param toRightMap
     *            此操作执行成功后，接收者的分配rightMap
     * @return true or false
     */
    @Override
    public boolean mortgage(HashMap<RightEnum, AbstractRight> moldMap, String[] froms,
        HashMap<String, Double> toRightMap) {
        // 1. 通过isHasImplementRight函数判断是否具有相应的操作权利
        if (!isHasImplementRight(MoldEnum.MORTGAGE_MOLD, moldMap, froms, this.threshold)) {
            // 没有相关操作权利
            return false;
        }

        // 2. 调用对应的权利注销函数，注销所有映射
        for (RightEnum rightEnum : operateTypeRightList(MoldEnum.MORTGAGE_MOLD)) {
            // 删除moldMap中rightEnum的映射关系
            Set<String> userAddressSet = new HashSet<>(moldMap.get(rightEnum).rightMap.keySet());
            for (String userAddress : userAddressSet) {
                moldMap.get(rightEnum).deleteRight(userAddress, moldMap.get(rightEnum).rightMap.get(userAddress));
            }
        }

        // 3. 调用对应的权利建立函数
        for (RightEnum rightEnum : operateTypeRightList(MoldEnum.MORTGAGE_MOLD)) {
            for (String userAddress : toRightMap.keySet()) {
                moldMap.get(rightEnum).initRight(userAddress, toRightMap.get(userAddress));
                if (!moldMap.containsKey(rightEnum)) {
                    // 不存在则返回false，映射关系应该上一步中添加了
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 馈赠操作，判断各权利是否均操作阈值，符合条件就执行。 规定了馈赠操作需要具有的权利，规定了馈赠操作需要完成的权利转移 目前假定进行馈赠操作，需要具有收益权，占有权，处分权，并且其具有的比例操作阈值
     * 同样存在和sell相同的问题，对于买房不破租的处理
     *
     * @param moldMap
     *            资产对象与权利对象的映射hashMap
     * @param froms
     *            调用此操作的同意者数组
     * @param toRightMap
     *            此操作执行成功后，接收者的分配rightMap
     * @return true or false
     */
    @Override
    public boolean gift(HashMap<RightEnum, AbstractRight> moldMap, String[] froms, HashMap<String, Double> toRightMap) {
        // 1. 通过isHasImplementRight函数判断是否具有相应的操作权利
        if (!isHasImplementRight(MoldEnum.GIFT_MOLD, moldMap, froms, this.threshold)) {
            // 没有相关操作权利
            return false;
        }

        // 2. 调用对应的权利注销函数，注销所有映射
        for (RightEnum rightEnum : operateTypeRightList(MoldEnum.GIFT_MOLD)) {
            // 删除moldMap中rightEnum的映射关系
            Set<String> userAddressSet = new HashSet<>(moldMap.get(rightEnum).rightMap.keySet());
            for (String userAddress : userAddressSet) {
                moldMap.get(rightEnum).deleteRight(userAddress, moldMap.get(rightEnum).rightMap.get(userAddress));
            }
        }

        // 3. 调用对应的权利建立函数
        for (RightEnum rightEnum : operateTypeRightList(MoldEnum.GIFT_MOLD)) {
            for (String userAddress : toRightMap.keySet()) {
                moldMap.get(rightEnum).initRight(userAddress, toRightMap.get(userAddress));
                if (!moldMap.containsKey(rightEnum)) {
                    // 不存在则返回false，映射关系应该上一步中添加了
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 销毁操作，判断各权利是否均操作阈值，符合条件就执行。 规定了销毁操作需要具有的权利，规定了销毁操作需要完成的权利转移 目前假定进行销毁操作，需要具有收益权，占有权，处分权，使用权，并且其具有的比例操作阈值
     *
     * @param moldMap
     *            资产对象与权利对象的映射hashMap
     * @param froms
     *            调用此操作的同意者数组
     * @return true or false
     */
    @Override
    public boolean destroy(HashMap<RightEnum, AbstractRight> moldMap, String... froms) {
        // 1. 通过isHasImplementRight函数判断是否具有相应的操作权利
        if (!isHasImplementRight(MoldEnum.DESTROY_MOLD, moldMap, froms, this.threshold)) {
            // 没有相关操作权利
            return false;
        }

        // 2. 调用对应的权利注销函数，注销所有映射
        for (RightEnum rightEnum : operateTypeRightList(MoldEnum.DESTROY_MOLD)) {
            // 删除moldMap中rightEnum的映射关系
            moldMap.remove(rightEnum);
        }
        return true;
    }

    /**
     *
     * @param assetId
     *            资产id
     * @param froms
     *            调用此操作的同意者数组
     * @param asset
     *            资产对象
     * @param moldMap
     *            资产对象与权利对象的映射hashMap
     * @return
     */
    @Override
    public boolean update(String assetId, String[] froms, Asset asset, HashMap<RightEnum, AbstractRight> moldMap) {
//        HashMap<RightEnum, AbstractRight> assetEquityOld = carMold.assetService.findMold(asset.getAssetId()).moldMap;
        // 通过isHasImplementRight函数判断是否具有相应的操作权利
        if (!isHasImplementRight(MoldEnum.UPDATE_MOLD, moldMap, froms, this.threshold)) {
            // 没有相关操作权利
            return false;
        }
//        // 调用AssetService里的updateAsset方法，对资产进行更新
//        carMold.assetService.updateAsset(asset);
        return true;
    }

    /**
     * 各操作规则需要的权利集合定义
     *
     * @param operateType
     *            资产的操作方法
     * @return 所需要的权利集合 TODO 操作规则需要补充或者修正
     */
    @Override
    public List<RightEnum> operateTypeRightList(MoldEnum operateType) {
        switch (operateType) {
            case SELL_MOLD:
            case GIFT_MOLD:
            case LEASE_MOLD:
            case DESTROY_MOLD:
                return Arrays.asList(RightEnum.USUFRUCT_RIGHT, RightEnum.USE_RIGHT,
                        RightEnum.POSSESS_RIGHT, RightEnum.DISPOSE_RIGHT);
            case UPDATE_MOLD:
            case MORTGAGE_MOLD:
                return Arrays.asList(RightEnum.DISPOSE_RIGHT);
            case LEASEReturn_MOLD:
                return Arrays.asList(RightEnum.USE_RIGHT, RightEnum.POSSESS_RIGHT);
            default:
                return Collections.emptyList();
        }
    }
}
